//帐号服的缓存池
//保存5分钟-->目的防止反复登录，造成数据库查询拥堵
//保存内容：帐号和加密过的密码(不保存原始密码)，和response
//response每次进来了会更新
import http = require('http');
import bcryptjs = require('bcryptjs');

export class Pool
{
    private _pool:Object;
    private static _instance:Pool;
    private _intervalId:NodeJS.Timer;

    public static getInstance():Pool
    {
        if(this._instance == null)
        {
            this._instance = new Pool();
        }

        return this._instance;
    }

    constructor()
    {
        this._pool = new Object();
    }

    public start():void
    {
        let self = this;
        //初始化一个循环事件
        this._intervalId = setInterval(function(){
            let curTime = new Date().getTime();
            for(let key in self._pool)
            {
                let obj:BaseObject = self._pool[key];
                if(obj.timestamp < curTime)
                {
                    //超过时间就删掉
                    self.deleteObj(key);
                }
            }
        },1000);
    }

    public dispose():void
    {
        clearInterval(this._intervalId);
    }

    public updateObj():void
    {
        
    }

    /**在创建的需要确保acc的唯一性 */
    public addObj(res:http.ServerResponse,acc:string,pwd:string):BaseObject
    {
        let obj:BaseObject;
        if(this._pool[acc])
        {
            obj = this._pool[acc];
            obj.res = res;
            obj.acc = acc;
            obj.pwd = pwd;
        }
        else
        {
            obj = new BaseObject();
            obj.res = res;
            obj.acc = acc;
            obj.pwd = pwd;
        }
        obj.updateDeadline();
        this._pool[acc] = obj;
        return this._pool[acc];
    }

    public deleteObj(acc:string):void
    {
        delete this._pool[acc];
    }

    /**有可能是空 */
    public getObj(acc:string):BaseObject
    {
        return this._pool[acc];
    }

    /**是否包含 */
    public contains(acc:string):boolean
    {
        return this._pool[acc]?true:false;
    }
}

//基础对象的信息
class BaseObject
{
    public res:http.ServerResponse;
    public acc:string;
    private _pwd:string;
    /**数据库里存的密码字段 */
    public dbpwd:string;
    /**没有_id说明还没有查询到数据 */
    public _id:object;
    /**过期时间 */
    public timestamp:number;

    public updateDeadline():void
    {
        this.timestamp = new Date().getTime() + 5*60*1000;
        console.warn("timestamp:",this.timestamp);
    }

    public set pwd(value:string)
    {
        this._pwd = value;
    }

    public get pwd():string
    {
        return this._pwd;
    }

    /**
     * 密码加密
     * @param callBack 回调函数，通知外部这个用户密码的hash已经生成
     *  */
    public pwdCoding(callBack:Function,thisObj:any,args:any):void
    {
        let self = this;
        // crypto
        bcryptjs.genSalt(10).then(function(value)
        {
            bcryptjs.hash(self.pwd,value).then(function(hash){
                self.dbpwd = hash;//生成hash
                callBack.call(thisObj,args,hash);
            }).catch(function(hashErr){
                console.warn('BaseObject.pwdCoding.hashErr',hashErr);
            });
        }).catch(function(saltErr){
            console.warn('BaseObject.pwdCoding.saltErr',saltErr);
        });
    }

    /**检测密码是匹配 */
    public checkPwd():Promise<boolean>
    {
        return bcryptjs.compare(this.pwd,this.dbpwd);
    }
}